package org.lts.yuqueexportor.service;

import lombok.extern.slf4j.Slf4j;
import org.lts.yuqueexportor.config.YuqueConfig;
import org.lts.yuqueexportor.entity.ExportResult;
import org.lts.yuqueexportor.entity.YuqueBook;
import org.lts.yuqueexportor.entity.YuqueDoc;
import org.lts.yuqueexportor.entity.YuqueGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 导出服务
 */
@Slf4j
@Service
public class ExportService {

    @Autowired
    private YuqueService yuqueService;

    @Autowired
    private FileService fileService;

    @Autowired
    private YuqueConfig yuqueConfig;

    /**
     * 执行导出任务
     */
    public void executeExport() {
        long startTime = System.currentTimeMillis();

        log.info("╔════════════════════════════════════════════════════════╗");
        log.info("║          语雀文档导出工具 - 开始执行              ║");
        log.info("╚════════════════════════════════════════════════════════╝");
        log.info("");
        log.info("保存路径: {}", fileService.getSavePath());
        log.info("");

        AtomicInteger totalBooks = new AtomicInteger(0);
        AtomicInteger totalDocs = new AtomicInteger(0);
        AtomicInteger successDocs = new AtomicInteger(0);
        AtomicInteger failedDocs = new AtomicInteger(0);

        try {
            // 1. 导出个人空间
            if (yuqueConfig.getIncludePersonal()) {
                log.info("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                log.info("  个人空间导出");
                log.info("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                exportPersonalSpace(totalBooks, totalDocs, successDocs, failedDocs);
            }

            // 2. 导出团队空间
            log.info("");
            log.info("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            log.info("  团队空间导出");
            log.info("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            exportTeamSpaces(totalBooks, totalDocs, successDocs, failedDocs);

        } catch (Exception e) {
            log.error("导出过程发生异常", e);
        }

        // 计算耗时
        long endTime = System.currentTimeMillis();
        long duration = (endTime - startTime) / 1000;

        // 输出统计信息
        log.info("");
        log.info("╔════════════════════════════════════════════════════════╗");
        log.info("║          导出完成 - 统计信息                      ║");
        log.info("╠════════════════════════════════════════════════════════╣");
        log.info("║  总知识库数: {:>8} 个                            ║", totalBooks.get());
        log.info("║  总文档数:   {:>8} 个                            ║", totalDocs.get());
        log.info("║  成功导出:   {:>8} 个  ✓                        ║", successDocs.get());
        log.info("║  导出失败:   {:>8} 个  ✗                        ║", failedDocs.get());
        log.info("║  耗时:       {:>8} 秒                            ║", duration);
        log.info("╠════════════════════════════════════════════════════════╣");
        log.info("║  保存路径: {}", fileService.getSavePath());
        log.info("╚════════════════════════════════════════════════════════╝");
    }

    /**
     * 导出个人空间
     */
    private void exportPersonalSpace(AtomicInteger totalBooks, AtomicInteger totalDocs,
                                      AtomicInteger successDocs, AtomicInteger failedDocs) throws IOException {
        List<YuqueBook> books = yuqueService.getPersonalBooks();
        totalBooks.addAndGet(books.size());

        for (YuqueBook book : books) {
            log.info("\n处理个人知识库: {} (ID: {}, type: {})", book.getName(), book.getId(), book.getType());

            // 跳过Resource类型的知识库(资源文件库),这类知识库使用不同的API
            if ("Resource".equals(book.getType())) {
                log.info("  跳过资源文件库类型,不导出");
                continue;
            }

            exportBook(book, "个人空间/" + book.getName(), totalDocs, successDocs, failedDocs);
        }
    }

    /**
     * 导出团队空间
     */
    private void exportTeamSpaces(AtomicInteger totalBooks, AtomicInteger totalDocs,
                                   AtomicInteger successDocs, AtomicInteger failedDocs) throws IOException {
        List<YuqueGroup> groups = yuqueService.getUserGroups();

        for (YuqueGroup group : groups) {
            // 如果配置了目标团队,则只导出指定团队
            if (yuqueConfig.getTargetGroups() != null && !yuqueConfig.getTargetGroups().isEmpty()) {
                if (!yuqueConfig.getTargetGroups().contains(group.getLogin())) {
                    log.info("跳过团队: {} ({})", group.getName(), group.getLogin());
                    continue;
                }
            }

            log.info("\n处理团队: {} ({})", group.getName(), group.getLogin());

            try {
                List<YuqueBook> books = yuqueService.getGroupBooks(group);
                totalBooks.addAndGet(books.size());

                for (YuqueBook book : books) {
                    log.info("\n  处理团队知识库: {} (ID: {}, type: {})", book.getName(), book.getId(), book.getType());

                    // 跳过Resource类型的知识库(资源文件库),这类知识库使用不同的API
                    if ("Resource".equals(book.getType())) {
                        log.info("    跳过资源文件库类型,不导出");
                        continue;
                    }

                    String dirName = group.getName() + "/" + book.getName();
                    exportBook(book, dirName, totalDocs, successDocs, failedDocs);
                }
            } catch (Exception e) {
                log.error("导出团队 {} 失败", group.getName(), e);
            }
        }
    }

    /**
     * 导出单个知识库的所有文档
     *
     * @param book        知识库对象
     * @param dirName     保存目录名称
     * @param totalDocs   总文档数计数器
     * @param successDocs 成功文档数计数器
     * @param failedDocs  失败文档数计数器
     */
    private void exportBook(YuqueBook book, String dirName,
                            AtomicInteger totalDocs, AtomicInteger successDocs, AtomicInteger failedDocs) {
        try {
            List<YuqueDoc> docs = yuqueService.getBookDocs(book);
            totalDocs.addAndGet(docs.size());

            if (docs.isEmpty()) {
                log.info("    知识库 [{}] 没有文档,跳过", book.getName());
                return;
            }

            String exportType = yuqueConfig.getExport().getType();
            log.info("    开始使用 [{}] 格式导出 {} 个文档", exportType, docs.size());

            for (int i = 0; i < docs.size(); i++) {
                YuqueDoc doc = docs.get(i);
                log.info("    [{}/{}] 导出文档: [{}]", (i + 1), docs.size(), doc.getTitle());

                try {
                    boolean success = false;

                    if ("markdown".equalsIgnoreCase(exportType)) {
                        // Markdown格式: 直接获取文档内容
                        success = exportDocAsMarkdown(doc, book, dirName, successDocs, failedDocs);
                    } else if ("word".equalsIgnoreCase(exportType)) {
                        // Word格式: 使用export API
                        success = exportDocAsWord(doc, dirName, successDocs, failedDocs);
                    } else if ("pdf".equalsIgnoreCase(exportType)) {
                        // PDF格式: 使用export API
                        success = exportDocAsPdf(doc, dirName, successDocs, failedDocs);
                    } else {
                        // 默认为Markdown
                        success = exportDocAsMarkdown(doc, book, dirName, successDocs, failedDocs);
                    }

                    if (success) {
                        log.info("      ✓ 成功");
                    } else {
                        log.warn("      ✗ 导出失败");
                    }

                    // 避免请求过快,防止触发限流
                    Thread.sleep(500);

                } catch (Exception e) {
                    log.error("      ✗ 导出失败: {}", e.getMessage());
                    failedDocs.incrementAndGet();
                }
            }
        } catch (Exception e) {
            log.error("  导出知识库 [{}] 失败: {}", book.getName(), e.getMessage());
        }
    }

    /**
     * 导出文档为Markdown格式
     */
    private boolean exportDocAsMarkdown(YuqueDoc doc, YuqueBook book, String dirName,
                                        AtomicInteger successDocs, AtomicInteger failedDocs) {
        try {
            ExportResult exportResult = yuqueService.exportDoc(doc, book);
            log.debug("      导出结果 - URL: {}, Status: {}", exportResult.getUrl(), exportResult.getStatus());

            if ("success".equals(exportResult.getStatus())) {
                if ("direct_markdown".equals(exportResult.getUrl())) {
                    String markdownContent = exportResult.getTaskId();
                    boolean saved = fileService.saveMarkdownContent(markdownContent, doc.getTitle(), dirName);
                    if (saved) {
                        successDocs.incrementAndGet();
                        return true;
                    } else {
                        failedDocs.incrementAndGet();
                        return false;
                    }
                }
            } else if ("empty_body".equals(exportResult.getStatus())) {
                // 文档内容为空,但已生成默认内容
                log.info("      文档内容为空,已生成默认内容");
                successDocs.incrementAndGet();
                return true;
            }

            failedDocs.incrementAndGet();
            return false;
        } catch (Exception e) {
            log.error("      ✗ Markdown导出失败: {}", e.getMessage());
            failedDocs.incrementAndGet();
            return false;
        }
    }

    /**
     * 导出文档为Word格式
     */
    private boolean exportDocAsWord(YuqueDoc doc, String dirName,
                                   AtomicInteger successDocs, AtomicInteger failedDocs) {
        try {
            ExportResult exportResult = yuqueService.exportDocToFormat(doc, "word");
            log.debug("      Word导出结果 - Status: {}", exportResult.getStatus());

            if ("success".equals(exportResult.getStatus())) {
                String downloadUrl = exportResult.getUrl();
                if (downloadUrl != null && !downloadUrl.isEmpty()) {
                    boolean saved = fileService.downloadAndSave(downloadUrl, dirName);
                    if (saved) {
                        successDocs.incrementAndGet();
                        return true;
                    }
                }
            } else if ("pending".equals(exportResult.getStatus())) {
                // 等待导出完成
                long docId = doc.getId();
                if (waitForExportCompletion(docId, "word")) {
                    ExportResult statusResult = yuqueService.pollExportStatus(docId, "word");
                    if ("success".equals(statusResult.getStatus())) {
                        boolean saved = fileService.downloadAndSave(statusResult.getUrl(), dirName);
                        if (saved) {
                            successDocs.incrementAndGet();
                            return true;
                        }
                    }
                }
            }

            failedDocs.incrementAndGet();
            return false;
        } catch (Exception e) {
            log.error("      ✗ Word导出失败: {}", e.getMessage());
            failedDocs.incrementAndGet();
            return false;
        }
    }

    /**
     * 导出文档为PDF格式
     */
    private boolean exportDocAsPdf(YuqueDoc doc, String dirName,
                                  AtomicInteger successDocs, AtomicInteger failedDocs) {
        try {
            ExportResult exportResult = yuqueService.exportDocToFormat(doc, "pdf");
            log.debug("      PDF导出结果 - Status: {}", exportResult.getStatus());

            if ("success".equals(exportResult.getStatus())) {
                String downloadUrl = exportResult.getUrl();
                if (downloadUrl != null && !downloadUrl.isEmpty()) {
                    boolean saved = fileService.downloadAndSave(downloadUrl, dirName);
                    if (saved) {
                        successDocs.incrementAndGet();
                        return true;
                    }
                }
            } else if ("pending".equals(exportResult.getStatus())) {
                // 等待导出完成
                long docId = doc.getId();
                if (waitForExportCompletion(docId, "pdf")) {
                    ExportResult statusResult = yuqueService.pollExportStatus(docId, "pdf");
                    if ("success".equals(statusResult.getStatus())) {
                        boolean saved = fileService.downloadAndSave(statusResult.getUrl(), dirName);
                        if (saved) {
                            successDocs.incrementAndGet();
                            return true;
                        }
                    }
                }
            }

            failedDocs.incrementAndGet();
            return false;
        } catch (Exception e) {
            log.error("      ✗ PDF导出失败: {}", e.getMessage());
            failedDocs.incrementAndGet();
            return false;
        }
    }

    /**
     * 等待导出完成
     */
    private boolean waitForExportCompletion(Long docId, String type) throws IOException {
        int maxRetries = 30;  // 最多重试30次,即30秒
        int retryInterval = 1000;  // 每次间隔1秒

        for (int i = 0; i < maxRetries; i++) {
            try {
                Thread.sleep(retryInterval);
                ExportResult status = yuqueService.pollExportStatus(docId, type);

                if ("success".equals(status.getStatus())) {
                    log.debug("      导出 [{}] 已完成", type);
                    return true;
                } else if ("failed".equals(status.getStatus())) {
                    log.debug("      导出 [{}] 失败", type);
                    return false;
                }

                log.debug("      等待导出完成... [{}/{}]", (i + 1), maxRetries);
            } catch (InterruptedException e) {
                log.error("      等待导出中断");
                return false;
            }
        }

        log.warn("      导出 [{}] 超时,已达到最大重试次数", type);
        return false;
    }
}
